package com.example.ssss.data;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleService;


import com.example.ssss.data.entity.MyMqttConMessage;
import com.example.ssss.data.entity.MyMqttMessage;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

/**
 * Author       wildma
 * Github       https://github.com/wildma
 * CreateDate   2018/11/08
 * Desc	        ${MQTT服务}
 */

public class MyMqttService extends LifecycleService{

    public final   String             TAG            = MyMqttService.class.getSimpleName();
    private static MqttAndroidClient  mqttAndroidClient;
    private        MqttConnectOptions mMqttConnectOptions;
    public         String             HOST           = "tcp://123.57.214.240:1883";//服务器地址（协议+地址+端口号）
    public         String             USERNAME       = "android";//用户名
    public         String             PASSWORD       = "android";//密码
    public static  String             PUBLISH_TOPIC  = "android";//发布主题
    public static  String             RESPONSE_TOPIC = "wear";//响应主题
    private boolean serviceRunning;
    private MyMqttMessage wheelData;
    private MyMqttMessage wearData;
    private MyMqttMessage envData;
    private MyMqttMessage behaveData;
    boolean wheelMsgReceived;
    boolean wearMsgReceived;
    boolean envMsgReceived;
    boolean behaveMsgReceived;
    String subTopics []={"ESP32_wheel_A0001","ESP32_env_E0001","ESP32_wear_W0001","RPI_behave_04EA56902CB0"};
    int qosArrs []={0,0,0,0};
    @SuppressLint("MissingPermission")
    public         String             CLIENTID       = MqttAsyncClient.generateClientId();//客户端ID，一般以客户端唯一标识符表示，这里用设备序列号表示


    @Override
    public void onCreate() {
        super.onCreate();
        serviceRunning = true;
        new Thread() {
            @Override
            public void run() {
                while (serviceRunning) {
                    MyMqttMessage myMqttMessage = null;
                    if(wheelMsgReceived) {
                        myMqttMessage = wheelData;
                        if (wheelCallback != null && myMqttMessage!=null) {
                            wheelCallback.wheelDataChanged(myMqttMessage);
                        }
                        wheelMsgReceived = false;
                    }
                    else if(wearMsgReceived){
                        myMqttMessage = wearData;
                        if(wearCallback != null && myMqttMessage!=null){
                            wearCallback.wearDataChanged(myMqttMessage);
                        }
                        wearMsgReceived = false;
                    }
                    else if(envMsgReceived){
                        myMqttMessage = envData;
                        if(envCallback != null && myMqttMessage!=null){
                            envCallback.envDataChanged(myMqttMessage);
                        }
                        envMsgReceived = false;
                    }
                    else if(behaveMsgReceived){
                        myMqttMessage = behaveData;
                        if(behaveCallback != null && myMqttMessage!=null){
                            behaveCallback.behaveDataChanged(myMqttMessage);
                        }
                        behaveMsgReceived = false;
                    }
                    try {
                        sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
        }.start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        MyServiceObserver myServiceObserver = new MyServiceObserver();
        getLifecycle().addObserver(myServiceObserver);
        try {
            wheelData = new MyMqttMessage();
            wearData = new MyMqttMessage();
            envData = new MyMqttMessage();
            behaveData = new MyMqttMessage();
            wheelMsgReceived = false;
            wearMsgReceived = false;
            envMsgReceived = false;
            behaveMsgReceived = false;
            init();
        } catch (MqttException e) {
            e.printStackTrace();
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        super.onBind(intent);
        return new LocalBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        serviceRunning = false;
        try {
            if(mqttAndroidClient != null){
                mqttAndroidClient.disconnect(); //断开连接
                mqttAndroidClient.unregisterResources();
            }

        } catch (MqttException e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }

    public class LocalBinder extends Binder{
        public  MyMqttService getService(){
            return  MyMqttService.this;
        }
    }
/***************************************************接口***********************************************/
    // 通过回调机制，将Service内部的变化传递到外部
    public interface WheelCallback {
        void wheelDataChanged(MyMqttMessage myMqttMessage);
    }
    public interface WearCallback{
        void wearDataChanged(MyMqttMessage myMqttMessage);
    }

    public interface EnvCallback{
        void envDataChanged(MyMqttMessage myMqttMessage);
    }

    public interface BehaveCallback{
        void behaveDataChanged(MyMqttMessage myMqttMessage);
    }

    WheelCallback wheelCallback = null;
    WearCallback wearCallback = null;
    EnvCallback envCallback = null;
    BehaveCallback behaveCallback = null;

    public void setWheelData(MyMqttMessage wheelData){
        MyMqttService.this.wheelData = wheelData;
    }

    public void setWearData(MyMqttMessage wearData){
        MyMqttService.this.wearData = wearData;
    }

    public void setEnvData(MyMqttMessage envData){
        MyMqttService.this.envData = envData;
    }
    public void setBehaveData(MyMqttMessage behaveData){
        MyMqttService.this.behaveData = behaveData;
    }

//    public WheelCallback getDataCallback() {
//        return wheelCallback;
//    }
//    public WearCallback getWearCallback() {
//        return wearCallback;
//    }

    public void setWheelDataCallback(WheelCallback wheelCallback) {//注意这里以单个回调为例  如果是向多个activity传送数据 可以定义一个回调集合 在此处进行集合的添加
        this.wheelCallback = wheelCallback;
    }

    public void setWearCallback(WearCallback wearCallback){
        this.wearCallback = wearCallback;
    }

    public void setEnvCallback(EnvCallback envCallback){
        this.envCallback = envCallback;
    }

    public void setBehaveCallback(BehaveCallback behaveCallback){
        this.behaveCallback = behaveCallback;
    }

/****************************************************动作***********************************************/



    /**
     * 响应 （收到其他客户端的消息后，响应给对方告知消息已到达或者消息有问题等）
     *
     * @param message 消息
     */
    public void response(String message) {
        String topic = RESPONSE_TOPIC;
        Integer qos = 2;
        Boolean retained = false;
        try {
            //参数分别为：主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息
            mqttAndroidClient.publish(topic, message.getBytes(), qos.intValue(), retained.booleanValue());
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化
     */
    private void init() throws MqttException {
        String serverURI = HOST; //服务器地址（协议+地址+端口号）
        mMqttConnectOptions = new MqttConnectOptions();
        mMqttConnectOptions.setCleanSession(true); //设置是否清除缓存
        mMqttConnectOptions.setConnectionTimeout(10); //设置超时时间，单位：秒
        mMqttConnectOptions.setKeepAliveInterval(20); //设置心跳包发送间隔，单位：秒
        mMqttConnectOptions.setUserName(USERNAME); //设置用户名
        mMqttConnectOptions.setPassword(PASSWORD.toCharArray()); //设置密码
        mqttAndroidClient = new MqttAndroidClient(this, serverURI, CLIENTID);
//        mqttServiceViewModel = ViewModelProviders.of(this).get(MyMqttServiceViewModel.class);
        //mqttServiceViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyMqttServiceViewModel.class);

        mqttAndroidClient.setCallback(new MqttCallbackExtended() {
            @Override
            public void connectComplete(boolean reconnect, String serverURI) {
                //断开连接必须重新订阅才能收到消息
                if(reconnect){
                    MyMqttConMessage msg = new MyMqttConMessage();
                    msg.setMessage("connect");
                    Log.e("重新订阅成功", "重新订阅成功 ");
                }
            }

            @Override
            public void connectionLost(Throwable cause) {
                Log.d("连接失败", "重连"+cause);
                doClientConnection();
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                String str2 = topic + ";qos:" + message.getQos() + ";retained:" + message.isRetained();
                Log.d(TAG, str2);
                String str1 = new String(message.getPayload());
                Log.d(TAG, "收到消息:" + str1);
                MyMqttMessage msg = new MyMqttMessage();
                msg.setMessage(str1);
                msg.setTopic(topic);
                //TODO 将消息发到其他view model
                if (topic.compareTo("ESP32_wheel_A0001") == 0){
                    wheelMsgReceived = true;
                    setWheelData(msg);
                }else if (topic.compareTo("ESP32_wear_W0001") == 0){
                    wearMsgReceived = true;
                    setWearData(msg);
                }else if(topic.compareTo("ESP32_env_E0001")==0){
                    envMsgReceived = true;
                    setEnvData(msg);
                }else if(topic.compareTo("RPI_behave_04EA56902CB0")==0){
                    behaveMsgReceived = true;
                    setBehaveData(msg);
                }
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {

            }
        }); //设置监听订阅消息的回调


        // last will message
        boolean doConnect = true;
        String message = "{\"terminal_uid\":\"" + CLIENTID + "\"}";
        String topic = PUBLISH_TOPIC;
        Integer qos = 2;
        Boolean retained = false;
        if ((!message.equals("")) || (!topic.equals(""))) {
            // 最后的遗嘱
            try {
                mMqttConnectOptions.setWill(topic, message.getBytes(), qos.intValue(), retained.booleanValue());
            } catch (Exception e) {
                Log.i(TAG, "Exception Occured", e);
                doConnect = false;
                iMqttActionListener.onFailure(null, e);
            }
        }
        if (doConnect) {
            doClientConnection();
        }
    }

    /**
     * 连接MQTT服务器
     */
    private void doClientConnection() {
        if (!mqttAndroidClient.isConnected() && isConnectIsNomarl()) {
            try {
                mqttAndroidClient.connect(mMqttConnectOptions, null, iMqttActionListener);
                //Toast.makeText(this,"成功连接MQTT",Toast.LENGTH_SHORT).show();
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }


    public void publish(String topic,String message) {
        int qos = 0;
        boolean retained = false;
//        if (!mqttAndroidClient.isConnected()){
//            doClientConnection();
//        }
        if (mqttAndroidClient != null && mqttAndroidClient.isConnected()) {
            try {
                //参数分别为：主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息
                mqttAndroidClient.publish(topic, message.getBytes(), qos, retained);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    public static boolean subscribe(String[] topicName, int qos[]){
        boolean flag = false;
        if (mqttAndroidClient != null && mqttAndroidClient.isConnected()) {
            try {

                mqttAndroidClient.subscribe(topicName, qos, null, new IMqttActionListener() {
                    @Override
                    public void onSuccess(IMqttToken asyncActionToken) {
                        Log.e("Subscribed","Subscribed");
                    }

                    @Override
                    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                        Log.e("Failed to subscribe","Failed to subscribe");

                    }
                });
                flag = true;
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
        else {

        }
        return flag;
    }
    /**
     * 判断网络是否连接
     */
    private boolean isConnectIsNomarl() {
        ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {
            String name = info.getTypeName();
            Log.i(TAG, "当前网络名称：" + name);
            return true;
        } else {
            Log.i(TAG, "没有可用网络");
            //Toast.makeText(this,"无可用网络，等待连接MQTT..." ,Toast.LENGTH_LONG).show();
            /*没有可用网络的时候，延迟2秒再尝试重连*/
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    doClientConnection();
                }
            }, 2000);
            return false;
        }
    }

    //MQTT是否连接成功的监听
    private IMqttActionListener iMqttActionListener = new IMqttActionListener() {
        @Override
        public void onSuccess(IMqttToken arg0) {
            Log.i(TAG, "连接成功 ");
            MyMqttConMessage msg = new MyMqttConMessage();
            msg.setMessage("connect");
            subscribe(subTopics,qosArrs);
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            arg1.printStackTrace();
            Log.i(TAG, "连接失败 ");
            MyMqttConMessage msg = new MyMqttConMessage();
            msg.setMessage("disconnect");
            doClientConnection();//连接失败，重连（可关闭服务器进行模拟）
        }
    };



}
